package com.drg.center.service.impl;

import cn.hutool.core.util.RandomUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.drg.center.dao.*;
import com.drg.center.entity.*;
import com.drg.center.entity.enums.DateTypeEnum;
import com.drg.center.entity.param.*;
import com.drg.center.entity.result.*;
import com.drg.center.service.BaseDealService;
import com.drg.center.service.DataStatAnalysisService;
import com.drg.center.service.StatisticsDoctorFromEsService;
import com.guaike.core.entity.result.PageEntity;
import com.guaike.core.entity.result.Result;
import com.guaike.core.utils.BigDecimalUtil;
import com.guaike.core.utils.ListUtil;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.servlet.http.HttpServletResponse;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.time.temporal.IsoFields;
import java.time.temporal.TemporalAdjusters;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;

@Slf4j
@Service
@AllArgsConstructor
public class DataStatAnalysisServiceImpl implements DataStatAnalysisService {

    private final DrgPatientCaseOutDAO drgPatientCaseOutDAO;
    private final DrgPatientCaseDiagnosisDAO drgPatientCaseDiagnosisDAO;
    private final EsCaseAngleDAO esCaseAngleDAO;
    private final BaseDealService baseDealService;
    private final EsDepartAngleDAO esDepartAngleDAO;
    private final DrgPatientCasePersonInfoDAO drgPatientCasePersonInfoDAO;
    private final DictDrgDAO dictDrgDAO;
    private final DictMdcDAO dictMdcDAO;
    private final StatisticsDoctorFromEsService statisticsDoctorFromEsService;
    private final DrgPatientCaseAdviceDAO drgPatientCaseAdviceDAO;


    @Override
    public Result<TotalDrgCostAnalysisVO> totalHospitalCostAnalysis(DrgCostAnalysisDTO param) {
        TotalDrgCostAnalysisVO vo = new TotalDrgCostAnalysisVO();
        LocalDate today = LocalDate.now();
        LocalDate startDate;
        LocalDate endDate;
        LocalDate startMonthDate = null;
        LocalDate endMonthDate = null;
        LocalDate startYearDate = null;
        LocalDate endYearDate = null;
        if (DateTypeEnum.today.getCode().equals(param.getDateType())) {
            startDate = today;
            endDate = today;
            startMonthDate = today.minusMonths(1);
            endMonthDate = today.minusMonths(1);
            startYearDate = today.minusYears(1);
            endYearDate = today.minusYears(1);
        } else if (DateTypeEnum.week.getCode().equals(param.getDateType())) {
            startDate = today.with(DayOfWeek.MONDAY);
            endDate = today.with(DayOfWeek.SUNDAY);
            startMonthDate = startDate.minusMonths(1);
            endMonthDate = endDate.minusMonths(1);
            startYearDate = startDate.minusYears(1);
            endYearDate = endDate.minusYears(1);
        } else if (DateTypeEnum.month.getCode().equals(param.getDateType())) {
            startDate = today.withDayOfMonth(1);
            endDate = today.with(TemporalAdjusters.lastDayOfMonth());
            startMonthDate = startDate.minusMonths(1);
            endMonthDate = endDate.minusMonths(1);
            startYearDate = startDate.minusYears(1);
            endYearDate = endDate.minusYears(1);
        } else if (DateTypeEnum.quarter.getCode().equals(param.getDateType())) {
            startDate = today.with(IsoFields.DAY_OF_QUARTER, 1);
            endDate = startDate.plusMonths(3).minusDays(1);
            startMonthDate = startDate.minusMonths(3);
            endMonthDate = endDate.minusMonths(3);
            startYearDate = startDate.minusYears(1);
            endYearDate = endDate.minusYears(1);
        } else if (DateTypeEnum.year.getCode().equals(param.getDateType())) {
            startDate = today.with(TemporalAdjusters.firstDayOfYear());
            endDate = today.with(TemporalAdjusters.lastDayOfYear());
            startYearDate = startDate.minusYears(1);
            endYearDate = endDate.minusYears(1);
        } else {
            startDate = today.with(TemporalAdjusters.firstDayOfYear());
            endDate = today.with(TemporalAdjusters.lastDayOfYear());
        }
        PatientCaseSttVO caseSttVO = esCaseAngleDAO.overveiw(null, startDate, endDate);
        BaseCardVO totalCase = new BaseCardVO();
        BaseCardVO diseaseGroup = new BaseCardVO();
        BaseCardVO groupRatio = new BaseCardVO();
        BaseCardVO totalTreatCost = new BaseCardVO();
        BaseCardVO totalPredictCost = new BaseCardVO();
        BaseCardVO totalActualCost = new BaseCardVO();
        BaseCardVO totalCost = new BaseCardVO();
        BaseCardVO caseAvgCost = new BaseCardVO();
        BaseCardVO medicineCost = new BaseCardVO();
        BaseCardVO medicineAvgCost = new BaseCardVO();
        BaseCardVO consumablesCost = new BaseCardVO();
        BaseCardVO consumablesAvgCost = new BaseCardVO();
        BaseCardVO otherCost = new BaseCardVO();
        BaseCardVO otherAvgCost = new BaseCardVO();
        if (Objects.nonNull(caseSttVO)) {
            totalCase.setTotalData(caseSttVO.getCaseCount().toString());
            diseaseGroup.setTotalData(caseSttVO.getDrgCount().toString());
            if (Objects.nonNull(caseSttVO.getCaseCount()) && caseSttVO.getCaseCount() > 0) {
                groupRatio.setTotalData(BigDecimalUtil.formatBigDecimal(new BigDecimal(caseSttVO.getCaseInDrgCount()).divide(new BigDecimal(caseSttVO.getCaseCount()), 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP)));
            }
            totalTreatCost.setTotalData(caseSttVO.getTotalCost().toPlainString());
            totalPredictCost.setTotalData(caseSttVO.getExpectCost().toPlainString());
            totalActualCost.setTotalData(caseSttVO.getTotalCost().toPlainString());
            totalCost.setTotalData(caseSttVO.getTotalCost().toPlainString());
            caseAvgCost.setTotalData(Objects.isNull(caseSttVO.getAvgCost()) ? "" : caseSttVO.getAvgCost().toPlainString());
            medicineCost.setTotalData(caseSttVO.getMedicineCost().toPlainString());
            medicineAvgCost.setTotalData(Objects.isNull(caseSttVO.getMedicineAvgCost()) ? "" : caseSttVO.getMedicineAvgCost().toPlainString());
            consumablesCost.setTotalData(caseSttVO.getConsumablesCost().toPlainString());
            consumablesAvgCost.setTotalData(Objects.isNull(caseSttVO.getConsumablesAvgCost()) ? "" : caseSttVO.getConsumablesAvgCost().toPlainString());
            otherCost.setTotalData(caseSttVO.getOtherCost().toPlainString());
            otherAvgCost.setTotalData(Objects.isNull(caseSttVO.getOtherAvgCost()) ? "" : caseSttVO.getOtherAvgCost().toPlainString());
        }
        if (Objects.nonNull(startMonthDate)) {
            PatientCaseSttVO caseMonthSttVO = esCaseAngleDAO.overveiw(null, startMonthDate, endMonthDate);
            if (Objects.nonNull(caseMonthSttVO)) {
                if (Objects.nonNull(caseMonthSttVO.getCaseCount()) && caseMonthSttVO.getCaseCount() > 0 && StringUtils.isNotBlank(totalCase.getTotalData())) {
                    BigDecimal subtract = new BigDecimal(totalCase.getTotalData()).subtract(new BigDecimal(caseMonthSttVO.getCaseCount()));
                    totalCase.setOnMonth(BigDecimalUtil.formatBigDecimal(subtract.divide(new BigDecimal(caseMonthSttVO.getCaseCount()), 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP)));
                }
                if (Objects.nonNull(caseMonthSttVO.getDrgCount()) && caseMonthSttVO.getDrgCount() > 0 && StringUtils.isNotBlank(totalCase.getTotalData())) {
                    BigDecimal subtract = new BigDecimal(diseaseGroup.getTotalData()).subtract(new BigDecimal(caseMonthSttVO.getDrgCount()));
                    diseaseGroup.setOnMonth(BigDecimalUtil.formatBigDecimal(subtract.divide(new BigDecimal(caseMonthSttVO.getDrgCount()), 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP)));
                }
                if (Objects.nonNull(caseMonthSttVO.getCaseInDrgCount()) && caseMonthSttVO.getCaseInDrgCount() > 0
                        && Objects.nonNull(caseMonthSttVO.getCaseCount()) && caseMonthSttVO.getCaseCount() > 0 && StringUtils.isNotBlank(groupRatio.getTotalData())) {
                    BigDecimal onGroupRate = new BigDecimal(caseMonthSttVO.getCaseInDrgCount()).divide(new BigDecimal(caseMonthSttVO.getCaseCount()), 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP);
                    BigDecimal subtract = new BigDecimal(groupRatio.getTotalData()).subtract(onGroupRate);
                    groupRatio.setOnMonth(BigDecimalUtil.formatBigDecimal(subtract.divide(onGroupRate, 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP)));
                }
                if (Objects.nonNull(caseMonthSttVO.getTotalCost()) && caseMonthSttVO.getTotalCost().doubleValue() > 0) {
                    BigDecimal subtract = new BigDecimal(totalTreatCost.getTotalData()).subtract(caseMonthSttVO.getTotalCost());
                    totalTreatCost.setOnMonth(BigDecimalUtil.formatBigDecimal(subtract.divide(caseMonthSttVO.getTotalCost(), 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP)));
                }
                if (Objects.nonNull(caseMonthSttVO.getExpectCost()) && caseMonthSttVO.getExpectCost().doubleValue() > 0) {
                    BigDecimal subtract = new BigDecimal(totalPredictCost.getTotalData()).subtract(caseMonthSttVO.getExpectCost());
                    totalPredictCost.setOnMonth(BigDecimalUtil.formatBigDecimal(subtract.divide(caseMonthSttVO.getExpectCost(), 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP)));
                }
                if (Objects.nonNull(caseMonthSttVO.getTotalCost()) && caseMonthSttVO.getTotalCost().doubleValue() > 0) {
                    BigDecimal subtract = new BigDecimal(totalTreatCost.getTotalData()).subtract(caseMonthSttVO.getTotalCost());
                    totalActualCost.setOnMonth(BigDecimalUtil.formatBigDecimal(subtract.divide(caseMonthSttVO.getTotalCost(), 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP)));
                }
                if (Objects.nonNull(caseMonthSttVO.getTotalCost()) && caseMonthSttVO.getTotalCost().doubleValue() > 0) {
                    BigDecimal subtract = new BigDecimal(totalTreatCost.getTotalData()).subtract(caseMonthSttVO.getTotalCost());
                    totalCost.setOnMonth(BigDecimalUtil.formatBigDecimal(subtract.divide(caseMonthSttVO.getTotalCost(), 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP)));
                }
                if (Objects.nonNull(caseMonthSttVO.getAvgCost()) && caseMonthSttVO.getAvgCost().doubleValue() > 0
                        && Objects.nonNull(caseSttVO.getAvgCost())) {
                    BigDecimal subtract = caseSttVO.getAvgCost().subtract(caseMonthSttVO.getAvgCost());
                    caseAvgCost.setOnMonth(BigDecimalUtil.formatBigDecimal(subtract.divide(caseMonthSttVO.getAvgCost(), 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP)));
                }
                if (Objects.nonNull(caseMonthSttVO.getMedicineCost()) && caseMonthSttVO.getMedicineCost().doubleValue() > 0
                        && Objects.nonNull(caseSttVO.getMedicineCost())) {
                    BigDecimal subtract = caseSttVO.getMedicineCost().subtract(caseMonthSttVO.getMedicineCost());
                    medicineCost.setOnMonth(BigDecimalUtil.formatBigDecimal(subtract.divide(caseMonthSttVO.getMedicineCost(), 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP)));
                }
                if (Objects.nonNull(caseMonthSttVO.getMedicineAvgCost()) && caseMonthSttVO.getMedicineAvgCost().doubleValue() > 0
                        && Objects.nonNull(caseSttVO.getMedicineAvgCost())) {
                    BigDecimal subtract = caseSttVO.getMedicineAvgCost().subtract(caseMonthSttVO.getMedicineAvgCost());
                    medicineAvgCost.setOnMonth(BigDecimalUtil.formatBigDecimal(subtract.divide(caseMonthSttVO.getMedicineAvgCost(), 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP)));
                }
                if (Objects.nonNull(caseMonthSttVO.getConsumablesCost()) && caseMonthSttVO.getConsumablesCost().doubleValue() > 0
                        && Objects.nonNull(caseSttVO.getConsumablesCost())) {
                    BigDecimal subtract = caseSttVO.getConsumablesCost().subtract(caseMonthSttVO.getConsumablesCost());
                    consumablesCost.setOnMonth(BigDecimalUtil.formatBigDecimal(subtract.divide(caseMonthSttVO.getConsumablesCost(), 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP)));
                }
                if (Objects.nonNull(caseMonthSttVO.getConsumablesAvgCost()) && caseMonthSttVO.getConsumablesAvgCost().doubleValue() > 0
                        && Objects.nonNull(caseSttVO.getConsumablesCost())) {
                    BigDecimal subtract = caseSttVO.getConsumablesAvgCost().subtract(caseMonthSttVO.getConsumablesAvgCost());
                    consumablesAvgCost.setOnMonth(BigDecimalUtil.formatBigDecimal(subtract.divide(caseMonthSttVO.getConsumablesAvgCost(), 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP)));
                }
                if (Objects.nonNull(caseMonthSttVO.getOtherCost()) && caseMonthSttVO.getOtherCost().doubleValue() > 0) {
                    BigDecimal subtract = caseSttVO.getOtherCost().subtract(caseMonthSttVO.getOtherCost());
                    otherCost.setOnMonth(BigDecimalUtil.formatBigDecimal(subtract.divide(caseMonthSttVO.getOtherCost(), 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP)));
                }
                if (Objects.nonNull(caseMonthSttVO.getOtherAvgCost()) && caseMonthSttVO.getOtherAvgCost().doubleValue() > 0) {
                    BigDecimal subtract = caseSttVO.getOtherAvgCost().subtract(caseMonthSttVO.getOtherAvgCost());
                    otherAvgCost.setOnMonth(BigDecimalUtil.formatBigDecimal(subtract.divide(caseMonthSttVO.getOtherAvgCost(), 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP)));
                }
            }
        }
        if (Objects.nonNull(startYearDate)) {
            PatientCaseSttVO caseYearSttVO = esCaseAngleDAO.overveiw(null, startYearDate, endYearDate);
            if (Objects.nonNull(caseYearSttVO)) {
                if (Objects.nonNull(caseYearSttVO.getCaseCount()) && caseYearSttVO.getCaseCount() > 0 && StringUtils.isNotBlank(totalCase.getTotalData())) {
                    BigDecimal subtract = new BigDecimal(totalCase.getTotalData()).subtract(new BigDecimal(caseYearSttVO.getCaseCount()));
                    totalCase.setOnYear(BigDecimalUtil.formatBigDecimal(subtract.divide(new BigDecimal(caseYearSttVO.getCaseCount()), 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP)));
                }
                if (Objects.nonNull(caseYearSttVO.getDrgCount()) && caseYearSttVO.getDrgCount() > 0 && StringUtils.isNotBlank(totalCase.getTotalData())) {
                    BigDecimal subtract = new BigDecimal(diseaseGroup.getTotalData()).subtract(new BigDecimal(caseYearSttVO.getDrgCount()));
                    diseaseGroup.setOnYear(BigDecimalUtil.formatBigDecimal(subtract.divide(new BigDecimal(caseYearSttVO.getDrgCount()), 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP)));
                }
                if (Objects.nonNull(caseYearSttVO.getCaseInDrgCount()) && caseYearSttVO.getCaseInDrgCount() > 0
                        && Objects.nonNull(caseYearSttVO.getCaseCount()) && caseYearSttVO.getCaseCount() > 0 && StringUtils.isNotBlank(groupRatio.getTotalData())) {
                    BigDecimal onGroupRate = new BigDecimal(caseYearSttVO.getCaseInDrgCount()).divide(new BigDecimal(caseYearSttVO.getCaseCount()), 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP);
                    BigDecimal subtract = new BigDecimal(groupRatio.getTotalData()).subtract(onGroupRate);
                    groupRatio.setOnYear(BigDecimalUtil.formatBigDecimal(subtract.divide(onGroupRate, 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP)));
                }
                if (Objects.nonNull(caseYearSttVO.getTotalCost()) && caseYearSttVO.getTotalCost().doubleValue() > 0) {
                    BigDecimal subtract = new BigDecimal(totalTreatCost.getTotalData()).subtract(caseYearSttVO.getTotalCost());
                    totalTreatCost.setOnYear(BigDecimalUtil.formatBigDecimal(subtract.divide(caseYearSttVO.getTotalCost(), 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP)));
                }
                if (Objects.nonNull(caseYearSttVO.getExpectCost()) && caseYearSttVO.getExpectCost().doubleValue() > 0) {
                    BigDecimal subtract = new BigDecimal(totalPredictCost.getTotalData()).subtract(caseYearSttVO.getExpectCost());
                    totalPredictCost.setOnYear(BigDecimalUtil.formatBigDecimal(subtract.divide(caseYearSttVO.getExpectCost(), 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP)));
                }
                if (Objects.nonNull(caseYearSttVO.getTotalCost()) && caseYearSttVO.getTotalCost().doubleValue() > 0) {
                    BigDecimal subtract = new BigDecimal(totalTreatCost.getTotalData()).subtract(caseYearSttVO.getTotalCost());
                    totalActualCost.setOnYear(BigDecimalUtil.formatBigDecimal(subtract.divide(caseYearSttVO.getTotalCost(), 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP)));
                }
                if (Objects.nonNull(caseYearSttVO.getTotalCost()) && caseYearSttVO.getTotalCost().doubleValue() > 0) {
                    BigDecimal subtract = new BigDecimal(totalTreatCost.getTotalData()).subtract(caseYearSttVO.getTotalCost());
                    totalCost.setOnYear(BigDecimalUtil.formatBigDecimal(subtract.divide(caseYearSttVO.getTotalCost(), 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP)));
                }
                if (Objects.nonNull(caseYearSttVO.getAvgCost()) && caseYearSttVO.getAvgCost().doubleValue() > 0) {
                    BigDecimal subtract = caseSttVO.getAvgCost().subtract(caseYearSttVO.getAvgCost());
                    caseAvgCost.setOnYear(BigDecimalUtil.formatBigDecimal(subtract.divide(caseYearSttVO.getAvgCost(), 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP)));
                }
                if (Objects.nonNull(caseYearSttVO.getMedicineCost()) && caseYearSttVO.getMedicineCost().doubleValue() > 0) {
                    BigDecimal subtract = caseSttVO.getMedicineCost().subtract(caseYearSttVO.getMedicineCost());
                    medicineCost.setOnYear(BigDecimalUtil.formatBigDecimal(subtract.divide(caseYearSttVO.getMedicineCost(), 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP)));
                }
                if (Objects.nonNull(caseYearSttVO.getMedicineAvgCost()) && caseYearSttVO.getMedicineAvgCost().doubleValue() > 0) {
                    BigDecimal subtract = caseSttVO.getMedicineAvgCost().subtract(caseYearSttVO.getMedicineAvgCost());
                    medicineAvgCost.setOnYear(BigDecimalUtil.formatBigDecimal(subtract.divide(caseYearSttVO.getMedicineAvgCost(), 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP)));
                }
                if (Objects.nonNull(caseYearSttVO.getConsumablesCost()) && caseYearSttVO.getConsumablesCost().doubleValue() > 0) {
                    BigDecimal subtract = caseSttVO.getConsumablesCost().subtract(caseYearSttVO.getConsumablesCost());
                    consumablesCost.setOnYear(BigDecimalUtil.formatBigDecimal(subtract.divide(caseYearSttVO.getConsumablesCost(), 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP)));
                }
                if (Objects.nonNull(caseYearSttVO.getConsumablesAvgCost()) && caseYearSttVO.getConsumablesAvgCost().doubleValue() > 0) {
                    BigDecimal subtract = caseSttVO.getConsumablesAvgCost().subtract(caseYearSttVO.getConsumablesAvgCost());
                    consumablesAvgCost.setOnYear(BigDecimalUtil.formatBigDecimal(subtract.divide(caseYearSttVO.getConsumablesAvgCost(), 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP)));
                }
                if (Objects.nonNull(caseYearSttVO.getOtherCost()) && caseYearSttVO.getOtherCost().doubleValue() > 0) {
                    BigDecimal subtract = caseSttVO.getOtherCost().subtract(caseYearSttVO.getOtherCost());
                    otherCost.setOnYear(BigDecimalUtil.formatBigDecimal(subtract.divide(caseYearSttVO.getOtherCost(), 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP)));
                }
                if (Objects.nonNull(caseYearSttVO.getOtherAvgCost()) && caseYearSttVO.getOtherAvgCost().doubleValue() > 0) {
                    BigDecimal subtract = caseSttVO.getOtherAvgCost().subtract(caseYearSttVO.getOtherAvgCost());
                    otherAvgCost.setOnYear(BigDecimalUtil.formatBigDecimal(subtract.divide(caseYearSttVO.getOtherAvgCost(), 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP)));
                }
            }
        }
        vo.setTotalCase(totalCase);
        vo.setDiseaseGroup(diseaseGroup);
        vo.setGroupRatio(groupRatio);
        vo.setTotalTreatCost(totalTreatCost);
        vo.setTotalPredictCost(totalPredictCost);
        vo.setTotalActualCost(totalActualCost);
        vo.setTotalCost(totalCost);
        vo.setCaseAvgCost(caseAvgCost);
        vo.setMedicineCost(medicineCost);
        vo.setMedicineAvgCost(medicineAvgCost);
        vo.setConsumablesCost(consumablesCost);
        vo.setConsumablesAvgCost(consumablesAvgCost);
        vo.setOtherCost(otherCost);
        vo.setOtherAvgCost(otherAvgCost);
        List<BaseSingleColumnChartVO> departProfitLossList = new ArrayList<>();
        List<KeyValueVO> departTop5 = esCaseAngleDAO.getDepartTop5(startDate, endDate);
        departTop5.forEach(po -> {
            BaseSingleColumnChartVO chartVO = new BaseSingleColumnChartVO();
            chartVO.setDataX(po.getDesc());
            chartVO.setDataY(po.getValue().toString());
            departProfitLossList.add(chartVO);
        });
        vo.setDepartProfitLossList(departProfitLossList);
        List<BaseSingleColumnChartVO> diseaseGroupProfitLossList = new ArrayList<>();
        List<KeyValueVO> drgTop5 = esCaseAngleDAO.getDrgTop5(null, startDate, endDate);
        drgTop5.forEach(po -> {
            BaseSingleColumnChartVO chartVO = new BaseSingleColumnChartVO();
            chartVO.setDataX(po.getDesc());
            chartVO.setDataY(po.getValue().toString());
            diseaseGroupProfitLossList.add(chartVO);
        });
        vo.setDiseaseGroupProfitLossList(diseaseGroupProfitLossList);
        List<CostColumnChartVO> costTrendList = new ArrayList<>();
        List<KeyValueVO> costTrend = esCaseAngleDAO.getCostTrend(today.getYear());
        costTrend.forEach(po -> {
            CostColumnChartVO chartVO = new CostColumnChartVO();
            chartVO.setDataX(po.getKey());
            chartVO.setActualY(po.getValue().toString());
            chartVO.setPredictY(po.getValue2().toString());
            costTrendList.add(chartVO);
        });
        vo.setCostTrendList(costTrendList);
        ProfitLossMixVO departMix = esCaseAngleDAO.getDepartProfitRateStt(startDate, endDate);
        vo.setDepartMix(departMix);
        ProfitLossMixVO groupMix = esCaseAngleDAO.getDrgProfitRateStt(null, startDate, endDate);
        vo.setGroupMix(groupMix);
        List<BaseSingleColumnChartVO> groupRatioList = new ArrayList<>();
        List<KeyValueVO> inDrgTrend = esCaseAngleDAO.getInDrgTrend(today.getYear());
        inDrgTrend.forEach(po -> {
            BaseSingleColumnChartVO chartVO = new BaseSingleColumnChartVO();
            chartVO.setDataX(po.getKey());
            chartVO.setDataY(po.getValue().toString());
            groupRatioList.add(chartVO);
        });
        vo.setGroupRatioList(groupRatioList);
        return Result.success().data(vo).build();
    }


    @Override
    public Result<PageEntity<CaseProfitLossPageVO>> caseProfitLossPage(CaseProfitLossDTO param) {
        PageEntity<CaseProfitLossPageVO> result = new PageEntity<>();
        long total = drgPatientCaseOutDAO.caseProfitLossPageCount(param);
        if (total == 0) {
            result.setList(new ArrayList<>());
            result.setTotal(total);
            return Result.success().data(result).build();
        }
        int start = (param.getPageIndex() - 1) * param.getPageSize();
        List<CaseProfitLossPageVO> vos = drgPatientCaseOutDAO.caseProfitLossPageList(start, param);
        vos.forEach(vo -> {
            DrgPatientCaseDiagnosisPO diagnosisPO = drgPatientCaseDiagnosisDAO.findMainOne(vo.getCaseCode());
            vo.setDiagnosisName(diagnosisPO.getDiagnosisName());
            BigDecimal avgCost = drgPatientCaseOutDAO.avgInHospitalCost(vo.getChsDrgCode());
            vo.setCaseAverageCost(avgCost);
            vo.setExpectedSurplus(vo.getTotalCost().subtract(avgCost));
            String referencePoints = baseDealService.calculateReferencePoints(vo.getChsDrgCode());
            vo.setReferencePoints(referencePoints);
        });
        result.setList(vos);
        result.setTotal(total);
        return Result.success().data(result).build();
    }

    @Override
    public void exportCaseProfitLosExcel(HttpServletResponse response, CaseProfitLossDTO param) throws Exception {
        int start = (param.getPageIndex() - 1) * param.getPageSize();
        List<CaseProfitLossPageVO> vos = drgPatientCaseOutDAO.caseProfitLossPageList(start, param);
        List<CaseProfitLossExcelVO> list = new ArrayList<>();
        vos.forEach(vo -> {
            CaseProfitLossExcelVO excelVO = new CaseProfitLossExcelVO();
            BeanUtils.copyProperties(vo, excelVO);
            DrgPatientCaseDiagnosisPO diagnosisPO = drgPatientCaseDiagnosisDAO.findMainOne(vo.getCaseCode());
            excelVO.setDiagnosisName(diagnosisPO.getDiagnosisName());
            if (Objects.nonNull(vo.getPatientAge())) {
                excelVO.setPatientAge(vo.getPatientAge() + "岁");
            }
            if (Objects.nonNull(vo.getAgeDay())) {
                excelVO.setPatientAge(vo.getAgeDay() + "天");
            }
            BigDecimal avgCost = drgPatientCaseOutDAO.avgInHospitalCost(vo.getChsDrgCode());
            excelVO.setCaseAverageCost(avgCost);
            excelVO.setExpectedSurplus(vo.getTotalCost().subtract(avgCost));
            String referencePoints = baseDealService.calculateReferencePoints(vo.getChsDrgCode());
            excelVO.setReferencePoints(referencePoints);
            list.add(excelVO);
        });
        OutputStream outputStream = getOutputStream(response, "病例盈亏预测表格.xlsx");
        EasyExcel.write(outputStream, CaseProfitLossExcelVO.class)
                .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
                .sheet("病例盈亏预测")
                .doWrite(list);
    }

    @Override
    public Result<PageEntity<CaseProfitLossAnalysisPageVO>> caseProfitLossAnalysisPage(CaseProfitLossDTO param) {
        PageEntity<CaseProfitLossAnalysisPageVO> result = new PageEntity<>();
        long total = drgPatientCaseOutDAO.caseProfitLossPageCount(param);
        if (total == 0) {
            result.setList(new ArrayList<>());
            result.setTotal(total);
            return Result.success().data(result).build();
        }
        int start = (param.getPageIndex() - 1) * param.getPageSize();
        List<CaseProfitLossAnalysisPageVO> list = new ArrayList<>();
        List<CaseProfitLossPageVO> vos = drgPatientCaseOutDAO.caseProfitLossPageList(start, param);
        vos.forEach(vo -> {
            CaseProfitLossAnalysisPageVO analysisVO = new CaseProfitLossAnalysisPageVO();
            BeanUtils.copyProperties(vo, analysisVO);
            BigDecimal avgCost = drgPatientCaseOutDAO.avgInHospitalCost(vo.getChsDrgCode());
            vo.setCaseAverageCost(avgCost);
            String referencePoints = baseDealService.calculateReferencePoints(vo.getChsDrgCode());
            analysisVO.setReferencePoints(referencePoints);
            String costMultiplier = baseDealService.calculateCostMultiplier(vo.getChsDrgCode());
            analysisVO.setCostMultiplier(costMultiplier);
            analysisVO.setTotalPoints(randomRate(70, 120).toPlainString());
            analysisVO.setCmi(randomRate(0, 1.5).toPlainString());
            analysisVO.setPointsAverageCost(vo.getTotalCost().divide(new BigDecimal(analysisVO.getTotalPoints()), 2, BigDecimal.ROUND_HALF_UP));
            analysisVO.setNetProfitLoss(vo.getCaseAverageCost().subtract(vo.getTotalCost()));
            list.add(analysisVO);
        });
        result.setList(list);
        result.setTotal(total);
        return Result.success().data(result).build();
    }

    @Override
    public Result<CaseProfitLossAnalysisVO> caseProfitLossAnalysis(CaseProfitLossDTO param) {
        CaseProfitLossAnalysisVO analysisVO = esCaseAngleDAO.caseProfitLossAnalysis(param);
        return Result.success().data(analysisVO).build();
    }

    @Override
    public void exportCaseProfitLossAnalysisExcel(HttpServletResponse response, CaseProfitLossDTO param) throws
            Exception {
        int start = (param.getPageIndex() - 1) * param.getPageSize();
        List<CaseProfitLossPageVO> vos = drgPatientCaseOutDAO.caseProfitLossPageList(start, param);
        List<CaseProfitLossAnalysisExcelVO> list = new ArrayList<>();
        vos.forEach(vo -> {
            CaseProfitLossAnalysisExcelVO excelVO = new CaseProfitLossAnalysisExcelVO();
            BeanUtils.copyProperties(vo, excelVO);
            if (Objects.nonNull(vo.getPatientAge())) {
                excelVO.setPatientAge(vo.getPatientAge() + "岁");
            }
            if (Objects.nonNull(vo.getAgeDay())) {
                excelVO.setPatientAge(vo.getAgeDay() + "天");
            }
            BigDecimal avgCost = drgPatientCaseOutDAO.avgInHospitalCost(vo.getChsDrgCode());
            vo.setCaseAverageCost(avgCost);
            String referencePoints = baseDealService.calculateReferencePoints(vo.getChsDrgCode());
            excelVO.setReferencePoints(referencePoints);
            String costMultiplier = baseDealService.calculateCostMultiplier(vo.getChsDrgCode());
            excelVO.setCostMultiplier(costMultiplier);
            excelVO.setTotalPoints(randomRate(70, 120).toPlainString());
            excelVO.setCmi(randomRate(0, 1.5).toPlainString());
            excelVO.setPointsAverageCost(vo.getTotalCost().divide(new BigDecimal(excelVO.getTotalPoints()), 2, BigDecimal.ROUND_HALF_UP));
            excelVO.setNetProfitLoss(vo.getCaseAverageCost().subtract(vo.getTotalCost()));
            list.add(excelVO);
        });
        OutputStream outputStream = getOutputStream(response, "病例盈亏分析表格.xlsx");
        EasyExcel.write(outputStream, CaseProfitLossAnalysisExcelVO.class)
                .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
                .sheet("病例盈亏分析")
                .doWrite(list);
    }

    @Override
    public Result<DepartDataVO> departDataOverview(DepartDataDTO param) {
        DepartDataVO vo = new DepartDataVO();
        LocalDate today = LocalDate.now();
        LocalDate startDate;
        LocalDate endDate;
        LocalDate startMonthDate = null;
        LocalDate endMonthDate = null;
        LocalDate startYearDate = null;
        LocalDate endYearDate = null;
        if (DateTypeEnum.today.getCode().equals(param.getDateType())) {
            startDate = today;
            endDate = today;
            startMonthDate = today.minusMonths(1);
            endMonthDate = today.minusMonths(1);
            startYearDate = today.minusYears(1);
            endYearDate = today.minusYears(1);
        } else if (DateTypeEnum.week.getCode().equals(param.getDateType())) {
            startDate = today.with(DayOfWeek.MONDAY);
            endDate = today.with(DayOfWeek.SUNDAY);
            startMonthDate = startDate.minusMonths(1);
            endMonthDate = endDate.minusMonths(1);
            startYearDate = startDate.minusYears(1);
            endYearDate = endDate.minusYears(1);
        } else if (DateTypeEnum.month.getCode().equals(param.getDateType())) {
            startDate = today.withDayOfMonth(1);
            endDate = today.with(TemporalAdjusters.lastDayOfMonth());
            startMonthDate = startDate.minusMonths(1);
            endMonthDate = endDate.minusMonths(1);
            startYearDate = startDate.minusYears(1);
            endYearDate = endDate.minusYears(1);
        } else if (DateTypeEnum.quarter.getCode().equals(param.getDateType())) {
            startDate = today.with(IsoFields.DAY_OF_QUARTER, 1);
            endDate = startDate.plusMonths(3).minusDays(1);
            startMonthDate = startDate.minusMonths(3);
            endMonthDate = endDate.minusMonths(3);
            startYearDate = startDate.minusYears(1);
            endYearDate = endDate.minusYears(1);
        } else if (DateTypeEnum.year.getCode().equals(param.getDateType())) {
            startDate = today.with(TemporalAdjusters.firstDayOfYear());
            endDate = today.with(TemporalAdjusters.lastDayOfYear());
            startYearDate = startDate.minusYears(1);
            endYearDate = endDate.minusYears(1);
        } else {
            startDate = today.with(TemporalAdjusters.firstDayOfYear());
            endDate = today.with(TemporalAdjusters.lastDayOfYear());
        }
        PatientCaseSttVO caseSttVO = esCaseAngleDAO.overveiw(param.getDepartCode(), startDate, endDate);
        BaseCardVO totalCase = new BaseCardVO();
        BaseCardVO diseaseGroup = new BaseCardVO();
        BaseCardVO groupRatio = new BaseCardVO();
        BaseCardVO totalTreatCost = new BaseCardVO();
        BaseCardVO totalPredictCost = new BaseCardVO();
        BaseCardVO totalActualCost = new BaseCardVO();
        BaseCardVO totalCost = new BaseCardVO();
        BaseCardVO caseAvgCost = new BaseCardVO();
        BaseCardVO medicineCost = new BaseCardVO();
        BaseCardVO medicineAvgCost = new BaseCardVO();
        BaseCardVO consumablesCost = new BaseCardVO();
        BaseCardVO consumablesAvgCost = new BaseCardVO();
        BaseCardVO otherCost = new BaseCardVO();
        BaseCardVO otherAvgCost = new BaseCardVO();
        if (Objects.nonNull(caseSttVO)) {
            totalCase.setTotalData(caseSttVO.getCaseCount().toString());
            diseaseGroup.setTotalData(caseSttVO.getDrgCount().toString());
            if (Objects.nonNull(caseSttVO.getCaseCount()) && caseSttVO.getCaseCount() > 0) {
                groupRatio.setTotalData(BigDecimalUtil.formatBigDecimal(new BigDecimal(caseSttVO.getCaseInDrgCount()).divide(new BigDecimal(caseSttVO.getCaseCount()), 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP)));
            }
            totalTreatCost.setTotalData(caseSttVO.getTotalCost().toPlainString());
            totalPredictCost.setTotalData(caseSttVO.getExpectCost().toPlainString());
            totalActualCost.setTotalData(caseSttVO.getTotalCost().toPlainString());
            totalCost.setTotalData(caseSttVO.getTotalCost().toPlainString());
            caseAvgCost.setTotalData(Objects.isNull(caseSttVO.getAvgCost()) ? "" : caseSttVO.getAvgCost().toPlainString());
            medicineCost.setTotalData(caseSttVO.getMedicineCost().toPlainString());
            medicineAvgCost.setTotalData(Objects.isNull(caseSttVO.getMedicineAvgCost()) ? "" : caseSttVO.getMedicineAvgCost().toPlainString());
            consumablesCost.setTotalData(caseSttVO.getConsumablesCost().toPlainString());
            consumablesAvgCost.setTotalData(Objects.isNull(caseSttVO.getConsumablesAvgCost()) ? "" : caseSttVO.getConsumablesAvgCost().toPlainString());
            otherCost.setTotalData(caseSttVO.getOtherCost().toPlainString());
            otherAvgCost.setTotalData(Objects.isNull(caseSttVO.getOtherAvgCost()) ? "" : caseSttVO.getOtherAvgCost().toPlainString());
        }
        if (Objects.nonNull(startMonthDate)) {
            PatientCaseSttVO caseMonthSttVO = esCaseAngleDAO.overveiw(param.getDepartCode(), startMonthDate, endMonthDate);
            if (Objects.nonNull(caseMonthSttVO)) {
                if (Objects.nonNull(caseMonthSttVO.getCaseCount()) && caseMonthSttVO.getCaseCount() > 0 && StringUtils.isNotBlank(totalCase.getTotalData())) {
                    BigDecimal subtract = new BigDecimal(totalCase.getTotalData()).subtract(new BigDecimal(caseMonthSttVO.getCaseCount()));
                    totalCase.setOnMonth(BigDecimalUtil.formatBigDecimal(subtract.divide(new BigDecimal(caseMonthSttVO.getCaseCount()), 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP)));
                }
                if (Objects.nonNull(caseMonthSttVO.getDrgCount()) && caseMonthSttVO.getDrgCount() > 0 && StringUtils.isNotBlank(totalCase.getTotalData())) {
                    BigDecimal subtract = new BigDecimal(diseaseGroup.getTotalData()).subtract(new BigDecimal(caseMonthSttVO.getDrgCount()));
                    diseaseGroup.setOnMonth(BigDecimalUtil.formatBigDecimal(subtract.divide(new BigDecimal(caseMonthSttVO.getDrgCount()), 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP)));
                }
                if (Objects.nonNull(caseMonthSttVO.getCaseInDrgCount()) && caseMonthSttVO.getCaseInDrgCount() > 0
                        && Objects.nonNull(caseMonthSttVO.getCaseCount()) && caseMonthSttVO.getCaseCount() > 0 && StringUtils.isNotBlank(groupRatio.getTotalData())) {
                    BigDecimal onGroupRate = new BigDecimal(caseMonthSttVO.getCaseInDrgCount()).divide(new BigDecimal(caseMonthSttVO.getCaseCount()), 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP);
                    BigDecimal subtract = new BigDecimal(groupRatio.getTotalData()).subtract(onGroupRate);
                    groupRatio.setOnMonth(BigDecimalUtil.formatBigDecimal(subtract.divide(onGroupRate, 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP)));
                }
                if (Objects.nonNull(caseMonthSttVO.getTotalCost()) && caseMonthSttVO.getTotalCost().longValue() > 0) {
                    BigDecimal subtract = new BigDecimal(totalTreatCost.getTotalData()).subtract(caseMonthSttVO.getTotalCost());
                    totalTreatCost.setOnMonth(BigDecimalUtil.formatBigDecimal(subtract.divide(caseMonthSttVO.getTotalCost(), 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP)));
                }
                if (Objects.nonNull(caseMonthSttVO.getExpectCost()) && caseMonthSttVO.getExpectCost().longValue() > 0) {
                    BigDecimal subtract = new BigDecimal(totalPredictCost.getTotalData()).subtract(caseMonthSttVO.getExpectCost());
                    totalPredictCost.setOnMonth(BigDecimalUtil.formatBigDecimal(subtract.divide(caseMonthSttVO.getExpectCost(), 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP)));
                }
                if (Objects.nonNull(caseMonthSttVO.getTotalCost()) && caseMonthSttVO.getTotalCost().doubleValue() > 0) {
                    BigDecimal subtract = new BigDecimal(totalTreatCost.getTotalData()).subtract(caseMonthSttVO.getTotalCost());
                    totalActualCost.setOnMonth(BigDecimalUtil.formatBigDecimal(subtract.divide(caseMonthSttVO.getTotalCost(), 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP)));
                }
                if (Objects.nonNull(caseMonthSttVO.getTotalCost()) && caseMonthSttVO.getTotalCost().doubleValue() > 0) {
                    BigDecimal subtract = new BigDecimal(totalTreatCost.getTotalData()).subtract(caseMonthSttVO.getTotalCost());
                    totalCost.setOnMonth(BigDecimalUtil.formatBigDecimal(subtract.divide(caseMonthSttVO.getTotalCost(), 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP)));
                }
                if (Objects.nonNull(caseMonthSttVO.getAvgCost()) && caseMonthSttVO.getAvgCost().doubleValue() > 0) {
                    BigDecimal subtract = caseSttVO.getAvgCost().subtract(caseMonthSttVO.getAvgCost());
                    caseAvgCost.setOnMonth(BigDecimalUtil.formatBigDecimal(subtract.divide(caseMonthSttVO.getAvgCost(), 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP)));
                }
                if (Objects.nonNull(caseMonthSttVO.getMedicineCost()) && caseMonthSttVO.getMedicineCost().doubleValue() > 0) {
                    BigDecimal subtract = caseSttVO.getMedicineCost().subtract(caseMonthSttVO.getMedicineCost());
                    medicineCost.setOnMonth(BigDecimalUtil.formatBigDecimal(subtract.divide(caseMonthSttVO.getMedicineCost(), 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP)));
                }
                if (Objects.nonNull(caseMonthSttVO.getMedicineAvgCost()) && caseMonthSttVO.getMedicineAvgCost().doubleValue() > 0) {
                    BigDecimal subtract = caseSttVO.getMedicineAvgCost().subtract(caseMonthSttVO.getMedicineAvgCost());
                    medicineAvgCost.setOnMonth(BigDecimalUtil.formatBigDecimal(subtract.divide(caseMonthSttVO.getMedicineAvgCost(), 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP)));
                }
                if (Objects.nonNull(caseMonthSttVO.getConsumablesCost()) && caseMonthSttVO.getConsumablesCost().doubleValue() > 0) {
                    BigDecimal subtract = caseSttVO.getConsumablesCost().subtract(caseMonthSttVO.getConsumablesCost());
                    consumablesCost.setOnMonth(BigDecimalUtil.formatBigDecimal(subtract.divide(caseMonthSttVO.getConsumablesCost(), 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP)));
                }
                if (Objects.nonNull(caseMonthSttVO.getConsumablesAvgCost()) && caseMonthSttVO.getConsumablesAvgCost().doubleValue() > 0) {
                    BigDecimal subtract = caseSttVO.getConsumablesAvgCost().subtract(caseMonthSttVO.getConsumablesAvgCost());
                    consumablesAvgCost.setOnMonth(BigDecimalUtil.formatBigDecimal(subtract.divide(caseMonthSttVO.getConsumablesAvgCost(), 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP)));
                }
                if (Objects.nonNull(caseMonthSttVO.getOtherCost()) && caseMonthSttVO.getOtherCost().doubleValue() > 0) {
                    BigDecimal subtract = caseSttVO.getOtherCost().subtract(caseMonthSttVO.getOtherCost());
                    otherCost.setOnMonth(BigDecimalUtil.formatBigDecimal(subtract.divide(caseMonthSttVO.getOtherCost(), 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP)));
                }
                if (Objects.nonNull(caseMonthSttVO.getOtherAvgCost()) && caseMonthSttVO.getOtherAvgCost().doubleValue() > 0) {
                    BigDecimal subtract = caseSttVO.getOtherAvgCost().subtract(caseMonthSttVO.getOtherAvgCost());
                    otherAvgCost.setOnMonth(BigDecimalUtil.formatBigDecimal(subtract.divide(caseMonthSttVO.getOtherAvgCost(), 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP)));
                }
            }
        }
        if (Objects.nonNull(startYearDate)) {
            PatientCaseSttVO caseYearSttVO = esCaseAngleDAO.overveiw(param.getDepartCode(), startYearDate, endYearDate);
            if (Objects.nonNull(caseYearSttVO)) {
                if (Objects.nonNull(caseYearSttVO.getCaseCount()) && caseYearSttVO.getCaseCount() > 0 && StringUtils.isNotBlank(totalCase.getTotalData())) {
                    BigDecimal subtract = new BigDecimal(totalCase.getTotalData()).subtract(new BigDecimal(caseYearSttVO.getCaseCount()));
                    totalCase.setOnYear(BigDecimalUtil.formatBigDecimal(subtract.divide(new BigDecimal(caseYearSttVO.getCaseCount()), 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP)));
                }
                if (Objects.nonNull(caseYearSttVO.getDrgCount()) && caseYearSttVO.getDrgCount() > 0 && StringUtils.isNotBlank(totalCase.getTotalData())) {
                    BigDecimal subtract = new BigDecimal(diseaseGroup.getTotalData()).subtract(new BigDecimal(caseYearSttVO.getDrgCount()));
                    diseaseGroup.setOnYear(BigDecimalUtil.formatBigDecimal(subtract.divide(new BigDecimal(caseYearSttVO.getDrgCount()), 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP)));
                }
                if (Objects.nonNull(caseYearSttVO.getCaseInDrgCount()) && caseYearSttVO.getCaseInDrgCount() > 0
                        && Objects.nonNull(caseYearSttVO.getCaseCount()) && caseYearSttVO.getCaseCount() > 0 && StringUtils.isNotBlank(groupRatio.getTotalData())) {
                    BigDecimal onGroupRate = new BigDecimal(caseYearSttVO.getCaseInDrgCount()).divide(new BigDecimal(caseYearSttVO.getCaseCount()), 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP);
                    BigDecimal subtract = new BigDecimal(groupRatio.getTotalData()).subtract(onGroupRate);
                    groupRatio.setOnYear(BigDecimalUtil.formatBigDecimal(subtract.divide(onGroupRate, 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP)));
                }
                if (Objects.nonNull(caseYearSttVO.getTotalCost()) && caseYearSttVO.getTotalCost().longValue() > 0) {
                    BigDecimal subtract = new BigDecimal(totalTreatCost.getTotalData()).subtract(caseYearSttVO.getTotalCost());
                    totalTreatCost.setOnYear(BigDecimalUtil.formatBigDecimal(subtract.divide(caseYearSttVO.getTotalCost(), 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP)));
                }
                if (Objects.nonNull(caseYearSttVO.getExpectCost()) && caseYearSttVO.getExpectCost().longValue() > 0) {
                    BigDecimal subtract = new BigDecimal(totalPredictCost.getTotalData()).subtract(caseYearSttVO.getExpectCost());
                    totalPredictCost.setOnYear(BigDecimalUtil.formatBigDecimal(subtract.divide(caseYearSttVO.getExpectCost(), 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP)));
                }
                if (Objects.nonNull(caseYearSttVO.getTotalCost()) && caseYearSttVO.getTotalCost().doubleValue() > 0) {
                    BigDecimal subtract = new BigDecimal(totalTreatCost.getTotalData()).subtract(caseYearSttVO.getTotalCost());
                    totalActualCost.setOnYear(BigDecimalUtil.formatBigDecimal(subtract.divide(caseYearSttVO.getTotalCost(), 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP)));
                }
                if (Objects.nonNull(caseYearSttVO.getTotalCost()) && caseYearSttVO.getTotalCost().doubleValue() > 0) {
                    BigDecimal subtract = new BigDecimal(totalTreatCost.getTotalData()).subtract(caseYearSttVO.getTotalCost());
                    totalCost.setOnYear(BigDecimalUtil.formatBigDecimal(subtract.divide(caseYearSttVO.getTotalCost(), 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP)));
                }
                if (Objects.nonNull(caseYearSttVO.getAvgCost()) && caseYearSttVO.getAvgCost().doubleValue() > 0) {
                    BigDecimal subtract = caseSttVO.getAvgCost().subtract(caseYearSttVO.getAvgCost());
                    caseAvgCost.setOnYear(BigDecimalUtil.formatBigDecimal(subtract.divide(caseYearSttVO.getAvgCost(), 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP)));
                }
                if (Objects.nonNull(caseYearSttVO.getMedicineCost()) && caseYearSttVO.getMedicineCost().doubleValue() > 0) {
                    BigDecimal subtract = caseSttVO.getMedicineCost().subtract(caseYearSttVO.getMedicineCost());
                    medicineCost.setOnYear(BigDecimalUtil.formatBigDecimal(subtract.divide(caseYearSttVO.getMedicineCost(), 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP)));
                }
                if (Objects.nonNull(caseYearSttVO.getMedicineAvgCost()) && caseYearSttVO.getMedicineAvgCost().doubleValue() > 0) {
                    BigDecimal subtract = caseSttVO.getMedicineAvgCost().subtract(caseYearSttVO.getMedicineAvgCost());
                    medicineAvgCost.setOnYear(BigDecimalUtil.formatBigDecimal(subtract.divide(caseYearSttVO.getMedicineAvgCost(), 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP)));
                }
                if (Objects.nonNull(caseYearSttVO.getConsumablesCost()) && caseYearSttVO.getConsumablesCost().doubleValue() > 0) {
                    BigDecimal subtract = caseSttVO.getConsumablesCost().subtract(caseYearSttVO.getConsumablesCost());
                    consumablesCost.setOnYear(BigDecimalUtil.formatBigDecimal(subtract.divide(caseYearSttVO.getConsumablesCost(), 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP)));
                }
                if (Objects.nonNull(caseYearSttVO.getConsumablesAvgCost()) && caseYearSttVO.getConsumablesAvgCost().doubleValue() > 0) {
                    BigDecimal subtract = caseSttVO.getConsumablesAvgCost().subtract(caseYearSttVO.getConsumablesAvgCost());
                    consumablesAvgCost.setOnYear(BigDecimalUtil.formatBigDecimal(subtract.divide(caseYearSttVO.getConsumablesAvgCost(), 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP)));
                }
                if (Objects.nonNull(caseYearSttVO.getOtherCost()) && caseYearSttVO.getOtherCost().doubleValue() > 0) {
                    BigDecimal subtract = caseSttVO.getOtherCost().subtract(caseYearSttVO.getOtherCost());
                    otherCost.setOnYear(BigDecimalUtil.formatBigDecimal(subtract.divide(caseYearSttVO.getOtherCost(), 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP)));
                }
                if (Objects.nonNull(caseYearSttVO.getOtherAvgCost()) && caseYearSttVO.getOtherAvgCost().doubleValue() > 0) {
                    BigDecimal subtract = caseSttVO.getOtherAvgCost().subtract(caseYearSttVO.getOtherAvgCost());
                    otherAvgCost.setOnYear(BigDecimalUtil.formatBigDecimal(subtract.divide(caseYearSttVO.getOtherAvgCost(), 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP)));
                }
            }
        }
        vo.setTotalCase(totalCase);
        vo.setDiseaseGroup(diseaseGroup);
        vo.setGroupRatio(groupRatio);
        vo.setTotalTreatCost(totalTreatCost);
        vo.setTotalPredictCost(totalPredictCost);
        vo.setTotalActualCost(totalActualCost);
        vo.setTotalCost(totalCost);
        vo.setCaseAvgCost(caseAvgCost);
        vo.setMedicineCost(medicineCost);
        vo.setMedicineAvgCost(medicineAvgCost);
        vo.setConsumablesCost(consumablesCost);
        vo.setConsumablesAvgCost(consumablesAvgCost);
        vo.setOtherCost(otherCost);
        vo.setOtherAvgCost(otherAvgCost);
        List<BaseSingleColumnChartVO> diseaseGroupProfitLossList = new ArrayList<>();
        List<KeyValueVO> drgTop5 = esCaseAngleDAO.getDrgTop5(param.getDepartCode(), startDate, endDate);
        drgTop5.forEach(po -> {
            BaseSingleColumnChartVO chartVO = new BaseSingleColumnChartVO();
            chartVO.setDataX(po.getDesc());
            chartVO.setDataY(po.getValue().toString());
            diseaseGroupProfitLossList.add(chartVO);
        });
        vo.setDiseaseGroupProfitLossList(diseaseGroupProfitLossList);
        ProfitLossMixVO groupMix = esCaseAngleDAO.getDrgProfitRateStt(param.getDepartCode(), startDate, endDate);
        vo.setGroupMix(groupMix);
        List<BaseSingleColumnChartVO> groupRatioList = new ArrayList<>();
        List<KeyValueVO> inDrgTrend = esCaseAngleDAO.getInDrgTrend(today.getYear());
        inDrgTrend.forEach(po -> {
            BaseSingleColumnChartVO chartVO = new BaseSingleColumnChartVO();
            chartVO.setDataX(po.getKey());
            chartVO.setDataY(po.getValue().toString());
            groupRatioList.add(chartVO);
        });
        vo.setGroupRatioList(groupRatioList);
        List<String> departCodeList = StringUtils.isBlank(param.getDepartCode()) ? null : Arrays.asList(param.getDepartCode());
        vo.setDepartAvgCost(esDepartAngleDAO.getDepartAvgCostTrend(2024, departCodeList));
        return Result.success().data(vo).build();
    }

    @Override
    public Result<List<DepartProfitLossPageVO>> departProfitLossAnalysis(DepartProfitLossDTO param) {
        List<DepartProfitLossPageVO> list = esDepartAngleDAO.getDepartProfitLossList(param.getDepartCode(), param.getStartDate(), param.getEndDate());
        return Result.success().data(list).build();
    }

    @Override
    public void exportDepartProfitLossAnalysisExcel(HttpServletResponse response, DepartProfitLossDTO param) throws
            Exception {
        List<DepartProfitLossPageVO> vos = esDepartAngleDAO.getDepartProfitLossList(param.getDepartCode(), param.getStartDate(), param.getEndDate());
        List<DepartProfitLossExcelVO> list = ListUtil.copyList(vos, DepartProfitLossExcelVO.class);
        OutputStream outputStream = getOutputStream(response, "科室盈亏分析表格.xlsx");
        EasyExcel.write(outputStream, DepartProfitLossExcelVO.class)
                .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
                .sheet("科室盈亏分析")
                .doWrite(list);
    }

    @Override
    public Result<List<DepartCostPageVO>> departCostAnalysis(DepartCostDTO param) {
        List<DepartCostPageVO> resultList = new ArrayList<>();
        List<DepartAngleSttVO> list = esDepartAngleDAO.getDepartCostSttList(param.getDepartCode(), param.getStartDate(), param.getEndDate());
        list.forEach(vo -> {
            DepartCostPageVO pageVO = new DepartCostPageVO();
            BeanUtils.copyProperties(vo, pageVO);
            pageVO.setCmi(randomRate(0.1, 1.5).toPlainString());
            pageVO.setWeight(randomRate(0, 2).toPlainString());
            pageVO.setCaseCount(vo.getCaseCount());
            pageVO.setPredictProfitLoss(vo.getExpectProfit());
            pageVO.setNetProfitLoss(vo.getProfit());
            pageVO.setOnMonth(randomRate(30, 100).toPlainString());
            pageVO.setOnMonthDiff(randomRate(1000000, 10000000).multiply(new BigDecimal(pageVO.getOnMonth())).divide(new BigDecimal(100), 2, BigDecimal.ROUND_HALF_UP).toPlainString());
            pageVO.setOnYear(randomRate(70, 100).toPlainString());
            pageVO.setOnYearDiff(randomRate(50000000, 100000000).multiply(new BigDecimal(pageVO.getOnMonth())).divide(new BigDecimal(100), 2, BigDecimal.ROUND_HALF_UP).toPlainString());
            pageVO.setCmiOnMonth(randomRate(30, 60).toPlainString());
            pageVO.setCmiOnYear(randomRate(40, 80).toPlainString());
            pageVO.setCmiChangeRate(randomRate(20, 40).toPlainString());
            pageVO.setDrugMix(BigDecimalUtil.formatBigDecimal(vo.getMedicineCost().divide(vo.getTotalCost(), 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100))) + "%");
            pageVO.setConsumablesMix(BigDecimalUtil.formatBigDecimal(vo.getConsumablesCost().divide(vo.getTotalCost(), 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100))) + "%");
            pageVO.setChineseTreatMix(BigDecimalUtil.formatBigDecimal(new BigDecimal(vo.getTraditionalCount()).divide(new BigDecimal(vo.getCaseCount()), 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100))) + "%");
            pageVO.setInHospitalAverage((vo.getInpatientDays() / vo.getCaseCount()) + "");
            pageVO.setCaseAverageCost(vo.getTotalCost().divide(new BigDecimal(vo.getCaseCount()), 2, BigDecimal.ROUND_HALF_UP));
            pageVO.setCaseAverageDrugCost(vo.getMedicineCost().divide(new BigDecimal(vo.getCaseCount()), 2, BigDecimal.ROUND_HALF_UP));
            pageVO.setOperationMix(BigDecimalUtil.formatBigDecimal(new BigDecimal(vo.getOperationCount()).divide(new BigDecimal(vo.getCaseCount()), 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100))) + "%");
            pageVO.setThreeOrFourOperationMix(BigDecimalUtil.formatBigDecimal(new BigDecimal(vo.getOperationLevelThreeOrFourCount()).divide(new BigDecimal(vo.getCaseCount()), 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100))) + "%");
            resultList.add(pageVO);
        });
        return Result.success().data(resultList).build();
    }

    @Override
    public void exportDepartCostAnalysisExcel(HttpServletResponse response, DepartCostDTO param) throws Exception {
        List<DepartAngleSttVO> vos = esDepartAngleDAO.getDepartCostSttList(param.getDepartCode(), param.getStartDate(), param.getEndDate());
        List<DepartCostExcelVO> list = new ArrayList<>();
        vos.forEach(vo -> {
            DepartCostExcelVO pageVO = new DepartCostExcelVO();
            BeanUtils.copyProperties(vo, pageVO);
            pageVO.setCmi(randomRate(0.1, 1.5).toPlainString());
            pageVO.setWeight(randomRate(0, 2).toPlainString());
            pageVO.setCaseCount(vo.getCaseCount());
            pageVO.setPredictProfitLoss(vo.getExpectProfit());
            pageVO.setNetProfitLoss(vo.getProfit());
            pageVO.setOnMonth(randomRate(30, 100).toPlainString());
            pageVO.setOnMonthDiff(randomRate(1000000, 10000000).multiply(new BigDecimal(pageVO.getOnMonth())).divide(new BigDecimal(100), 2, BigDecimal.ROUND_HALF_UP).toPlainString());
            pageVO.setOnYear(randomRate(70, 100).toPlainString());
            pageVO.setOnYearDiff(randomRate(50000000, 100000000).multiply(new BigDecimal(pageVO.getOnMonth())).divide(new BigDecimal(100), 2, BigDecimal.ROUND_HALF_UP).toPlainString());
            pageVO.setCmiOnMonth(randomRate(30, 60).toPlainString());
            pageVO.setCmiOnYear(randomRate(40, 80).toPlainString());
            pageVO.setCmiChangeRate(randomRate(20, 40).toPlainString());
            pageVO.setDrugMix(BigDecimalUtil.formatBigDecimal(vo.getMedicineCost().divide(vo.getTotalCost(), 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100))) + "%");
            pageVO.setConsumablesMix(BigDecimalUtil.formatBigDecimal(vo.getConsumablesCost().divide(vo.getTotalCost(), 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100))) + "%");
            pageVO.setChineseTreatMix(BigDecimalUtil.formatBigDecimal(new BigDecimal(vo.getTraditionalCount()).divide(new BigDecimal(vo.getCaseCount()), 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100))) + "%");
            pageVO.setInHospitalAverage((vo.getInpatientDays() / vo.getCaseCount()) + "");
            pageVO.setCaseAverageCost(vo.getTotalCost().divide(new BigDecimal(vo.getCaseCount()), 2, BigDecimal.ROUND_HALF_UP));
            pageVO.setCaseAverageDrugCost(vo.getMedicineCost().divide(new BigDecimal(vo.getCaseCount()), 2, BigDecimal.ROUND_HALF_UP));
            pageVO.setOperationMix(BigDecimalUtil.formatBigDecimal(new BigDecimal(vo.getOperationCount()).divide(new BigDecimal(vo.getCaseCount()), 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100))) + "%");
            pageVO.setThreeOrFourOperationMix(BigDecimalUtil.formatBigDecimal(new BigDecimal(vo.getOperationLevelThreeOrFourCount()).divide(new BigDecimal(vo.getCaseCount()), 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100))) + "%");
            list.add(pageVO);
        });
        OutputStream outputStream = getOutputStream(response, "科室费用分析汇总表格.xlsx");
        EasyExcel.write(outputStream, DepartCostExcelVO.class)
                .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
                .sheet("科室费用分析汇总")
                .doWrite(list);
    }

    @Override
    public Result<List<DrgProfitLossPageVO>> drgProfitLossAnalysis(DrgProfitLossDTO param) {
        List<DrgProfitLossPageVO> result = new ArrayList<>();
        List<DrgAngleSttVO> list = esDepartAngleDAO.getDrgProfitLossList(param.getDepartCode(), param.getChsDrgCode(), param.getStartDate(), param.getEndDate());
        list.forEach(vo -> {
            DrgProfitLossPageVO pageVO = new DrgProfitLossPageVO();
            BeanUtils.copyProperties(vo, pageVO);
            pageVO.setChsDrgName(vo.getDrgName());
            pageVO.setNetProfitLoss(vo.getProfit());
            pageVO.setCaseAverageNetProfitLoss(vo.getProfit().divide(new BigDecimal(vo.getCaseCount()), 2, BigDecimal.ROUND_HALF_UP));
            pageVO.setDepartName(vo.getLossMostDepartName());
            pageVO.setCaseAverageCost(vo.getTotalCost().divide(new BigDecimal(vo.getCaseCount()), 2, BigDecimal.ROUND_HALF_UP));
            pageVO.setTotalPoints(randomRate(70, 120).toPlainString());
            pageVO.setRw(randomRate(0, 10).toPlainString());
            pageVO.setReferencePoints(randomRate(70, 100).toPlainString());
            pageVO.setCasePoints(randomRate(1, 1.5).multiply(new BigDecimal(pageVO.getReferencePoints())).toPlainString());
            pageVO.setPointsAverageCost(vo.getTotalCost().divide(new BigDecimal(pageVO.getTotalPoints()), 2, BigDecimal.ROUND_HALF_UP));
            result.add(pageVO);
        });
        return Result.success().data(result).build();
    }

    @Override
    public void exportDrgProfitLossAnalysisExcel(HttpServletResponse response, DrgProfitLossDTO param) throws
            Exception {
        List<DrgAngleSttVO> vos = esDepartAngleDAO.getDrgProfitLossList(param.getDepartCode(), param.getChsDrgCode(), param.getStartDate(), param.getEndDate());
        List<DrgProfitLossExcelVO> list = new ArrayList<>();
        vos.forEach(vo -> {
            DrgProfitLossExcelVO pageVO = new DrgProfitLossExcelVO();
            BeanUtils.copyProperties(vo, pageVO);
            pageVO.setChsDrgName(vo.getDrgName());
            pageVO.setNetProfitLoss(vo.getProfit());
            pageVO.setCaseAverageNetProfitLoss(vo.getProfit().divide(new BigDecimal(vo.getCaseCount()), 2, BigDecimal.ROUND_HALF_UP));
            pageVO.setDepartName(vo.getLossMostDepartName());
            pageVO.setCaseAverageCost(vo.getTotalCost().divide(new BigDecimal(vo.getCaseCount()), 2, BigDecimal.ROUND_HALF_UP));
            pageVO.setTotalPoints(randomRate(70, 120).toPlainString());
            pageVO.setRw(randomRate(0, 10).toPlainString());
            pageVO.setReferencePoints(randomRate(70, 100).toPlainString());
            pageVO.setCasePoints(randomRate(1, 1.5).multiply(new BigDecimal(pageVO.getReferencePoints())).toPlainString());
            pageVO.setPointsAverageCost(vo.getTotalCost().divide(new BigDecimal(pageVO.getTotalPoints()), 2, BigDecimal.ROUND_HALF_UP));
            list.add(pageVO);
        });
        OutputStream outputStream = getOutputStream(response, "病组盈亏分析表格.xlsx");
        EasyExcel.write(outputStream, DrgProfitLossExcelVO.class)
                .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
                .sheet("病组盈亏分析")
                .doWrite(list);
    }

    @Override
    public Result<PageEntity<MedicalProtestPageVO>> medicalProtestStat(MedicalProtestDTO param) {
        PageEntity<MedicalProtestPageVO> result = new PageEntity<>();
        Page<DrgPatientCaseOutPO> poPage = drgPatientCaseOutDAO.medicalProtestStat(param);
        List<MedicalProtestPageVO> list = new ArrayList<>();
        poPage.getRecords().forEach(po -> {
            MedicalProtestPageVO pageVO = new MedicalProtestPageVO();
            BeanUtils.copyProperties(po, pageVO);
            DrgPatientCasePersonInfoPO personInfoPO = drgPatientCasePersonInfoDAO.findOne(DrgPatientCasePersonInfoPO::getCaseCode, po.getCaseCode());
            pageVO.setPatientName(personInfoPO.getPatientName());
            pageVO.setPatientSex(personInfoPO.getPatientSex());
            pageVO.setPatientAge(personInfoPO.getPatientAge());
            pageVO.setAgeDay(personInfoPO.getAgeDay());
            pageVO.setMedicareType(personInfoPO.getMedicareType());
            pageVO.setIdCard(personInfoPO.getIdCard());
            list.add(pageVO);
        });
        result.setList(list);
        result.setTotal(poPage.getTotal());
        return Result.success().data(result).build();
    }

    @Override
    public void exportMedicalProtestStatExcel(HttpServletResponse response, MedicalProtestDTO param) throws
            Exception {
        Page<DrgPatientCaseOutPO> poPage = drgPatientCaseOutDAO.medicalProtestStat(param);
        List<MedicalProtestExcelVO> list = ListUtil.copyList(poPage.getRecords(), MedicalProtestExcelVO.class);
        OutputStream outputStream = getOutputStream(response, "医保拒付统计表格.xlsx");
        EasyExcel.write(outputStream, MedicalProtestExcelVO.class)
                .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
                .sheet("医保拒付统计")
                .doWrite(list);
    }

    @Override
    public Result<PageEntity<MedicalTotalPageVO>> medicalTotalStat(MedicalTotalDTO param) {
        return null;
    }

    @Override
    public void exportMedicalTotalStatExcel(HttpServletResponse response, MedicalTotalDTO param) throws Exception {
        List<MedicalTotalExcelVO> list = new ArrayList<>();
        OutputStream outputStream = getOutputStream(response, "医保总额预付统计表格.xlsx");
        EasyExcel.write(outputStream, MedicalTotalExcelVO.class)
                .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
                .sheet("医保总额预付统计")
                .doWrite(list);
    }

    @Override
    public Result<List<SampleDataPageVO>> SampleDataFind() {
        List<SampleDataPageVO> list = new ArrayList<>();
        List<DrgAngleSttVO> vos = esDepartAngleDAO.getDrgProfitLossList(null, null, null, null);
        vos.forEach(vo -> {
            SampleDataPageVO pageVO = new SampleDataPageVO();
            pageVO.setDrgCode(vo.getDrgCode());
            pageVO.setDrgName(vo.getDrgName());
            pageVO.setCaseAverageInHospitalCost(vo.getTotalCost().divide(new BigDecimal(vo.getCaseCount()), 2, BigDecimal.ROUND_HALF_UP));
            pageVO.setCaseInHospitalAverageDay((vo.getInpatientDays() / vo.getCaseCount()) + "");
            pageVO.setDieCaseCount(vo.getDealthCase());
            pageVO.setInDrgCaseCount(vo.getCaseCount());
            DictDrgPO drgPO = dictDrgDAO.findOne(DictDrgPO::getDrgCode, vo.getDrgCode());
            pageVO.setWeight(Objects.isNull(drgPO.getDrgWeight()) ? "" : drgPO.getDrgWeight().toPlainString());
            pageVO.setDrgCostStandard(drgPO.getDrgCostStandard());
            if (!drgPO.getDrgCode().equals("0000")) {
                char c = drgPO.getDrgCode().charAt(0);
                pageVO.setMdcCode("MDC" + c);
                DictMdcPO mdcPO = dictMdcDAO.findOne(DictMdcPO::getMdcCode, pageVO.getMdcCode());
                pageVO.setMdcName(mdcPO.getMdcName());
            }
            list.add(pageVO);
        });
        return Result.success().data(list).build();
    }

    @Override
    public void exportSampleDataFindExcel(HttpServletResponse response) throws Exception {
        List<SampleDataExcelVO> list = new ArrayList<>();
        List<DrgAngleSttVO> vos = esDepartAngleDAO.getDrgProfitLossList(null, null, null, null);
        vos.forEach(vo -> {
            SampleDataExcelVO pageVO = new SampleDataExcelVO();
            pageVO.setDrgCode(vo.getDrgCode());
            pageVO.setDrgName(vo.getDrgName());
            pageVO.setCaseAverageInHospitalCost(vo.getTotalCost().divide(new BigDecimal(vo.getCaseCount()), 2, BigDecimal.ROUND_HALF_UP));
            pageVO.setCaseInHospitalAverageDay((vo.getInpatientDays() / vo.getCaseCount()) + "");
            pageVO.setDieCaseCount(vo.getDealthCase());
            pageVO.setInDrgCaseCount(vo.getCaseCount());
            DictDrgPO drgPO = dictDrgDAO.findOne(DictDrgPO::getDrgCode, vo.getDrgCode());
            pageVO.setWeight(Objects.isNull(drgPO.getDrgWeight()) ? "" : drgPO.getDrgWeight().toPlainString());
            pageVO.setDrgCostStandard(drgPO.getDrgCostStandard());
            list.add(pageVO);
        });
        OutputStream outputStream = getOutputStream(response, "样本数据查询表格.xlsx");
        EasyExcel.write(outputStream, SampleDataExcelVO.class)
                .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
                .sheet("样本数据查询")
                .doWrite(list);
    }


    @Override
    public void doctorGroupProfitLossTotalExportExcel(HttpServletResponse response, DoctorGroupSummaryDTO param) throws Exception {
        List<DoctorGoupSummaryVO> vos = statisticsDoctorFromEsService.getDoctorGoupSummaryVO(param);
        List<DoctorGoupSummaryExcelVO> list = ListUtil.copyList(vos, DoctorGoupSummaryExcelVO.class);
        OutputStream outputStream = getOutputStream(response, "医生组盈亏汇总表格.xlsx");
        EasyExcel.write(outputStream, DoctorGoupSummaryExcelVO.class)
                .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
                .sheet("医生组盈亏汇总")
                .doWrite(list);
    }

    @Override
    public Result<DoctorGroupProfitLossAnalysisVO> doctorGroupProfitLossAnalysis(DoctorGroupProfitDTO param) {
        DoctorGroupProfitLossAnalysisVO analysisVO = new DoctorGroupProfitLossAnalysisVO();
        LocalDate today = LocalDate.now();
        int year = today.getYear();
        LocalDate startDate;
        LocalDate endDate;
        if (DateTypeEnum.today.getCode().equals(param.getDateType())) {
            startDate = today;
            endDate = today;
        } else if (DateTypeEnum.week.getCode().equals(param.getDateType())) {
            startDate = today.with(DayOfWeek.MONDAY);
            endDate = today.with(DayOfWeek.SUNDAY);
        } else if (DateTypeEnum.month.getCode().equals(param.getDateType())) {
            startDate = today.withDayOfMonth(1);
            endDate = today.with(TemporalAdjusters.lastDayOfMonth());
        } else if (DateTypeEnum.quarter.getCode().equals(param.getDateType())) {
            startDate = today.with(IsoFields.DAY_OF_QUARTER, 1);
            endDate = startDate.plusMonths(3).minusDays(1);
        } else if (DateTypeEnum.year.getCode().equals(param.getDateType())) {
            startDate = today.with(TemporalAdjusters.firstDayOfYear());
            endDate = today.with(TemporalAdjusters.lastDayOfYear());
        } else {
            startDate = param.getStartDate() == null ? today.with(TemporalAdjusters.firstDayOfYear()) : param.getStartDate();
            endDate = param.getEndDate() == null ? today.with(TemporalAdjusters.lastDayOfYear()) : param.getEndDate();
        }
        List<KeyValueVO> valueVOS = statisticsDoctorFromEsService.getDoctorGroupProfitStt(startDate, endDate);
        analysisVO.setProfitLossList(valueVOS);
        ProfitLossMixVO lossMixVO = statisticsDoctorFromEsService.getDoctorGroupProfitRateStt(startDate, endDate);
        analysisVO.setProfitLossMixVO(lossMixVO);
        ChartLineVO chartLineVO = statisticsDoctorFromEsService.getDoctorGroupProfitTrendVO(startDate.getYear());
        analysisVO.setChartLineVO(chartLineVO);
        return Result.success().data(analysisVO).build();
    }

    @Override
    public void doctorProfitLossTotalExportExcel(HttpServletResponse response, DoctorSummaryDTO param) throws Exception {
        List<DoctorSummaryVO> vos = statisticsDoctorFromEsService.getDoctorSummaryVO(param);
        List<DoctorSummaryExcelVO> list = ListUtil.copyList(vos, DoctorSummaryExcelVO.class);
        OutputStream outputStream = getOutputStream(response, "医生盈亏汇总表格.xlsx");
        EasyExcel.write(outputStream, DoctorSummaryExcelVO.class)
                .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
                .sheet("医生盈亏汇总")
                .doWrite(list);
    }

    @Override
    public Result<DoctorProfitLossAnalysisVO> doctorProfitLossAnalysis(DoctorProfitDTO param) {
        DoctorProfitLossAnalysisVO vo = new DoctorProfitLossAnalysisVO();
        LocalDate today = LocalDate.now();
        int year = today.getYear();
        LocalDate startDate;
        LocalDate endDate;
        if (DateTypeEnum.today.getCode().equals(param.getDateType())) {
            startDate = today;
            endDate = today;
        } else if (DateTypeEnum.week.getCode().equals(param.getDateType())) {
            startDate = today.with(DayOfWeek.MONDAY);
            endDate = today.with(DayOfWeek.SUNDAY);
        } else if (DateTypeEnum.month.getCode().equals(param.getDateType())) {
            startDate = today.withDayOfMonth(1);
            endDate = today.with(TemporalAdjusters.lastDayOfMonth());
        } else if (DateTypeEnum.quarter.getCode().equals(param.getDateType())) {
            startDate = today.with(IsoFields.DAY_OF_QUARTER, 1);
            endDate = startDate.plusMonths(3).minusDays(1);
        } else if (DateTypeEnum.year.getCode().equals(param.getDateType())) {
            startDate = today.with(TemporalAdjusters.firstDayOfYear());
            endDate = today.with(TemporalAdjusters.lastDayOfYear());
        } else {
            startDate = param.getStartDate() == null ? today.with(TemporalAdjusters.firstDayOfYear()) : param.getStartDate();
            endDate = param.getEndDate() == null ? today.with(TemporalAdjusters.lastDayOfYear()) : param.getEndDate();
        }
        ProfitLossMixVO lossMixVO = statisticsDoctorFromEsService.getDoctorProfitRateStt(startDate, endDate);
        vo.setProfitLossMixVO(lossMixVO);
        List<KeyValueVO> profitTop5 = statisticsDoctorFromEsService.getDoctorProfitTop5(startDate, endDate);
        vo.setProfitList(profitTop5);
        List<KeyValueVO> lossTop5 = statisticsDoctorFromEsService.getDoctorLossTop5(startDate, endDate);
        vo.setLossList(lossTop5);
        ChartLineVO chartLineVO = statisticsDoctorFromEsService.getDoctorCostTrend(startDate.getYear(), param.getDoctorCodeList());
        vo.setChartLineVO(chartLineVO);
        return Result.success().data(vo).build();
    }

    @Override
    public Result<DrgProfitLossAnalysisVO> drgProfitLossAnalysisStat(DrgProfitDTO param) {
        DrgProfitLossAnalysisVO vo = new DrgProfitLossAnalysisVO();
        LocalDate today = LocalDate.now();
        int year = today.getYear();
        LocalDate startDate;
        LocalDate endDate;
        if (DateTypeEnum.today.getCode().equals(param.getDateType())) {
            startDate = today;
            endDate = today;
        } else if (DateTypeEnum.week.getCode().equals(param.getDateType())) {
            startDate = today.with(DayOfWeek.MONDAY);
            endDate = today.with(DayOfWeek.SUNDAY);
        } else if (DateTypeEnum.month.getCode().equals(param.getDateType())) {
            startDate = today.withDayOfMonth(1);
            endDate = today.with(TemporalAdjusters.lastDayOfMonth());
        } else if (DateTypeEnum.quarter.getCode().equals(param.getDateType())) {
            startDate = today.with(IsoFields.DAY_OF_QUARTER, 1);
            endDate = startDate.plusMonths(3).minusDays(1);
        } else if (DateTypeEnum.year.getCode().equals(param.getDateType())) {
            startDate = today.with(TemporalAdjusters.firstDayOfYear());
            endDate = today.with(TemporalAdjusters.lastDayOfYear());
        } else {
            startDate = param.getStartDate() == null ? today.with(TemporalAdjusters.firstDayOfYear()) : param.getStartDate();
            endDate = param.getEndDate() == null ? today.with(TemporalAdjusters.lastDayOfYear()) : param.getEndDate();
        }
        ChartLineVO chartLineVO = statisticsDoctorFromEsService.getDrgProfitTrend(startDate.getYear(), param.getDrgCodeList());
        vo.setChartLineVO(chartLineVO);
        ChartLineVO lineVO = statisticsDoctorFromEsService.getDrgAvgCostTrend(startDate.getYear(), param.getDrgCodeList());
        vo.setLineVO(lineVO);
        DifficultCaseDistributeVO distribute = statisticsDoctorFromEsService.getDifficultCaseDistribute(param.getDrgCodeList(), startDate, endDate);
        vo.setDistributeVO(distribute);
        return Result.success().data(vo).build();
    }

    @Override
    public Result<List<DrgProfitLossProjectTotalPageVO>> drgProfitLossProjectTotalStat(DrgProfitLossProjectTotalStatDTO param) {
        List<DrgProfitLossProjectTotalPageVO> vos = statisticsDoctorFromEsService.getDrgProjectStt(param.getDepartCode(), param.getChsDrgCode(), param.getStartDate(), param.getEndDate());
        return Result.success().data(vos).build();
    }

    @Override
    public void drgProfitLossProjectTotalStatExcel(HttpServletResponse response, DrgProfitLossProjectTotalStatDTO param) throws Exception {
        List<DrgProfitLossProjectTotalPageVO> vos = statisticsDoctorFromEsService.getDrgProjectStt(param.getDepartCode(), param.getChsDrgCode(), param.getStartDate(), param.getEndDate());
        List<DrgProfitLossProjectTotalExcelVO> list = ListUtil.copyList(vos, DrgProfitLossProjectTotalExcelVO.class);
        OutputStream outputStream = getOutputStream(response, "病组盈亏项目统计表格.xlsx");
        EasyExcel.write(outputStream, DrgProfitLossProjectTotalExcelVO.class)
                .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
                .sheet("病组盈亏项目统计")
                .doWrite(list);
    }

    @Override
    public Result<List<CaseComplexityAnalysisPageVO>> caseComplexityAnalysis(CaseComplexityAnalysisDTO param) {
        List<CaseComplexityAnalysisPageVO> vos = statisticsDoctorFromEsService.getComplexity(param.getDepartCode(), param.getStartDate(), param.getEndDate());
        return Result.success().data(vos).build();
    }

    @Override
    public void caseComplexityAnalysisExcel(HttpServletResponse response, CaseComplexityAnalysisDTO param) throws Exception {
        List<CaseComplexityAnalysisPageVO> vos = statisticsDoctorFromEsService.getComplexity(param.getDepartCode(), param.getStartDate(), param.getEndDate());
        List<CaseComplexityAnalysisExcelVO> list = ListUtil.copyList(vos, CaseComplexityAnalysisExcelVO.class);
        OutputStream outputStream = getOutputStream(response, "病例复杂程度分析表格.xlsx");
        EasyExcel.write(outputStream, CaseComplexityAnalysisExcelVO.class)
                .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
                .sheet("病例复杂程度分析")
                .doWrite(list);
    }

    @Override
    public Result<PageEntity<KeyProjectsTotalStatPageVO>> keyProjectsTotalStat(KeyProjectsTotalStatExcelDTO param) {
        int start = (param.getPageIndex() - 1) * param.getPageSize();
        long count = drgPatientCaseOutDAO.keyProjectsTotalStatPageCount(param);
        PageEntity<KeyProjectsTotalStatPageVO> result = new PageEntity<>();
        if (count == 0) {
            return Result.success().data(result).build();
        }
        List<KeyProjectsTotalStatPageVO> list = drgPatientCaseOutDAO.keyProjectsTotalStatPage(start, param);
        list.forEach(vo -> {
            DrgPatientCaseOutPO outPO = drgPatientCaseOutDAO.findOne(DrgPatientCaseOutPO::getCaseCode, vo.getCaseCode());
            BeanUtils.copyProperties(outPO, vo);
            DrgPatientCasePersonInfoPO personInfoPO = drgPatientCasePersonInfoDAO.findOne(DrgPatientCasePersonInfoPO::getCaseCode, vo.getCaseCode());
            BeanUtils.copyProperties(personInfoPO, vo);
            List<DrgPatientCaseAdvicePO> pos = drgPatientCaseAdviceDAO.findCaseAdvice(vo.getCaseCode(), vo.getProjectCode());
            vo.setKeyProjectName(pos.get(0).getAdviceContent());
            long sum = pos.stream().mapToLong(po -> ChronoUnit.SECONDS.between(po.getStartTime(), po.getEndTime())).sum();
            vo.setUseTime(String.valueOf(sum));
        });
        result.setList(list);
        result.setTotal(count);
        return Result.success().data(result).build();
    }

    @Override
    public void keyProjectsTotalStatExcel(HttpServletResponse response, KeyProjectsTotalStatExcelDTO param) throws Exception {
        long count = drgPatientCaseOutDAO.keyProjectsTotalStatPageCount(param);
        param.setPageSize((int) count);
        List<KeyProjectsTotalStatExcelVO> excelVOS = new ArrayList<>();
        List<KeyProjectsTotalStatPageVO> list = drgPatientCaseOutDAO.keyProjectsTotalStatPage(0, param);
        list.forEach(vo -> {
            KeyProjectsTotalStatExcelVO excelVO = new KeyProjectsTotalStatExcelVO();
            DrgPatientCaseOutPO outPO = drgPatientCaseOutDAO.findOne(DrgPatientCaseOutPO::getCaseCode, vo.getCaseCode());
            BeanUtils.copyProperties(outPO, excelVO);
            DrgPatientCasePersonInfoPO personInfoPO = drgPatientCasePersonInfoDAO.findOne(DrgPatientCasePersonInfoPO::getCaseCode, vo.getCaseCode());
            BeanUtils.copyProperties(personInfoPO, excelVO);
            List<DrgPatientCaseAdvicePO> pos = drgPatientCaseAdviceDAO.findCaseAdvice(vo.getCaseCode(), vo.getProjectCode());
            excelVO.setKeyProjectName(pos.get(0).getAdviceContent());
            long sum = pos.stream().mapToLong(po -> ChronoUnit.SECONDS.between(po.getStartTime(), po.getEndTime())).sum();
            excelVO.setUseTime(String.valueOf(sum));
            excelVOS.add(excelVO);
        });
        OutputStream outputStream = getOutputStream(response, "重点项目统计表格.xlsx");
        EasyExcel.write(outputStream, KeyProjectsTotalStatExcelVO.class)
                .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
                .sheet("重点项目统计")
                .doWrite(list);
    }

    /**
     * 导出时生成OutputStream
     */
    private static OutputStream getOutputStream(HttpServletResponse response, String fileName) throws Exception {
        response.setContentType("application/vnd.ms-excel");
        response.setCharacterEncoding("utf-8");
        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName);
        return response.getOutputStream();
    }

    private static BigDecimal randomRate(double min, double max) {
        return BigDecimal.valueOf(RandomUtil.randomDouble(min, max, 2, RoundingMode.HALF_UP));
    }
}
